import { Voucher } from "./Voucher";
import Attribute from "./VoucherBuild/Attribute";
import { Topbar } from "./VoucherBuild/Topbar";
import NodeLayer from "./VoucherBuild/NodeLayer";
import BaseNode from "./BaseNode";
import { EDIT_CLASS_NAME, inputTemplateData, tableTemplateData, textTemplateData, voucherTemplateData } from "../const";
import TextNodeBuild from "./VoucherBuild/nodes/TextNodeBuild";
import InputNodeBuild from "./VoucherBuild/nodes/InputNodeBuild";
import TableNodeBuild from "./VoucherBuild/nodes/TableNodeBuild";


export class VoucherBuild extends Voucher {

  private _attribute?: Attribute;
  private _topbar?: Topbar
  private _nodeLayer?: NodeLayer

  private _moveNode: BaseNode = new BaseNode();

  private get moveNode() {
    return this._moveNode
  }

  private set moveNode(data: BaseNode) {
    this._moveNode = data;
    if (!data.element) return;
    this.selectNode = data
  }

  private moveNodeStartPos: { top: number, left: number } = { top: 0, left: 0 };
  private moveNodeParentStartPos: { top: number, left: number } = { top: 0, left: 0 };


  private _selectNode: BaseNode

  private get selectNode() {
    return this._selectNode
  }

  private set selectNode(node: BaseNode) {
    if (this._selectNode === node) return;
    // 重置之前的选中节点
    this._selectNode.element?.classList.remove("selected")
    // 设置新的选中节点
    this._selectNode = node;

    this._onSelectNode(node)

  }

  protected get options() {
    return { ...this._options }
  }

  protected set options(data: VoucherTemplate) {
    this._options = data;
    this.renderVoucher(); // 渲染单据模板
  }

  constructor(el: Element | string, options: VoucherTemplate = voucherTemplateData()) {
    super(el, options);
    this.element.classList.add(EDIT_CLASS_NAME)
    this._selectNode = this // 初始选中单据本身
    this._onSelectNode(this)
    this.initMoveNode();
  }
  // 渲染构造工具栏
  protected rendToolbars() {
    this.createTopbar(); // 顶部工具栏
    this.createNodeLayer(); // 左侧节点图层
    this.createAttribute(); // 右侧属性图层
  }

  private _onSelectNode(node: BaseNode) {
    node.element?.classList.add("selected")
    if (node.nodeType === "voucher") {
      this._attribute?.setOptions(node.nodeType, this.options);
      this._nodeLayer?.setActiveNode()
    } else {
      const options = node.getOptions();
      this._attribute?.setOptions(node.nodeType, options as any);
      this._nodeLayer?.setActiveNode(node)
    }
  }



  protected createNode(type: "input" | "table" | "text", nodeData?: any) {
    let node: BaseNode | null = null
    if (type === "text") {
      node = new TextNodeBuild(nodeData || textTemplateData())
    } else if (type === "input") {
      node = new InputNodeBuild(nodeData || inputTemplateData())
    } else if (type === "table") {
      node = new TableNodeBuild(nodeData || tableTemplateData())
    }
    if (node) {
      node.setMenuView(this.menuView)
      this.nodes.push(node)
      this.addMoveEvent(node)
      this.addClickEvent(node)
      if (node.element) this.element.appendChild(node.element);
      if (this._nodeLayer) this._nodeLayer.nodes = this.nodes;
    }
    return node
  }

  protected createTopbar() {
    this._topbar = new Topbar(this._rootEl);
    this._topbar.onCreateNode(type => {
      const newNode = this.createNode(type)
      if (!newNode) return
      this.selectNode = newNode
    })
    this._topbar.onMethodChange(type => {
      switch (type) {
        case "select":
          this.element.classList.remove("move", "copy")
          this.element.classList.add("select")
          break;
        case "move":
          this.element.classList.remove("select", "copy")
          this.element.classList.add("move")
          break;
        case "copy":
          this.element.classList.remove("select", "move")
          this.element.classList.add("copy")
          break;
      }
    })

  }

  protected createNodeLayer() {
    this._nodeLayer = new NodeLayer(this._rootEl, this.nodes); // 创建节点层
    this._nodeLayer.onClickNode(node => this.selectNode = node)
  }

  protected createAttribute() {
    this._attribute = new Attribute(this._rootEl);
    this._attribute.onChange((type, key, value) => {
      if (type === "voucher") {
        if (key === "bg") {
          this.options = Object.assign({}, this.options, { bg: value ? (value instanceof File ? URL.createObjectURL(value) : value) : '' });
        } else {
          this.options = Object.assign({}, this.options, { [key]: value });
        }
      } else {
        this.selectNode.setOptions({ [key]: value })
        this._nodeLayer?.updateNode(this.selectNode)
      }
    })
  }

  /**
   * 为节点添加点击事件
   * @param type 节点类型
   * @param nodeEl 节点元素
   */
  private addClickEvent(node: BaseNode) {
    if (!node.element) return
    node.element.onclick = e => {
      e.stopPropagation();
      this.menuView.open = false
      if (this._topbar?.methodType === "select") {
        this.selectNode = node
      } else if (this._topbar?.methodType === "copy" && node.nodeType !== "voucher") {
        const options = node.getOptions()
        options.x += 5
        options.y += 5
        const newNode = this.createNode(node.nodeType, options)
        if (!newNode) return
        this.selectNode = newNode
      }
    }
  }

  /**
   * 为节点添加移动事件
   * @param type 节点类型
   * @param nodeEl 节点元素
   */
  private addMoveEvent(node: BaseNode) {
    if (!node.element) return
    node.element.onmousedown = (e) => {
      if (!node.element) return
      e.stopPropagation();
      if (this._topbar?.methodType !== "move") return
      this.moveNode = node
      // 获取元素相对于视口的位置
      var rect = node.element.getBoundingClientRect();
      // 获取相对于视口的坐标
      var x = e.clientX;
      var y = e.clientY;
      // 计算相对于元素本身的坐标
      var relX = x - rect.left;
      var relY = y - rect.top;
      // 获取鼠标在当前元素中的点击位置
      this.moveNodeStartPos = { left: relX, top: relY };
      const { top, left } = node.element.parentElement?.getBoundingClientRect() || { top: 0, left: 0 };
      this.moveNodeParentStartPos = { top, left }
    }
  }


  /**
   * 移动节点
   */
  private initMoveNode() {
    this.addMoveEvent(this) // 初始化为票据添加移动事件
    this._viewAreaEl.onmousemove = (e) => {
      if (!this.moveNode.element || this._topbar?.methodType !== "move") return
      const parentTop = this.moveNodeParentStartPos.top; // 父元素在窗口中的位置
      const parentLeft = this.moveNodeParentStartPos.left; // 父元素在窗口中的位置
      // 获取当前鼠标相对于父级元素的位置
      const currentPos = { top: e.clientY - parentTop, left: e.clientX - parentLeft };
      // 计算移动的距离
      const distance = { top: currentPos.top - this.moveNodeStartPos.top, left: currentPos.left - this.moveNodeStartPos.left };
      // 设置元素的位置
      if (this.moveNode.nodeType === "voucher") {
        this.moveNode.element.style.top = `${distance.top}px`;
        this.moveNode.element.style.left = `${distance.left}px`;
      } else {
        this.moveNode.setOptions({ x: distance.left, y: distance.top })
        this._attribute?.setOptions(this.moveNode.nodeType, this.moveNode.getOptions() as any)
      }
    }

    const stopMove = () => {
      this.element.onmousemove = null;
      this.element.onmouseup = null;
      if (!this.moveNode.element) return
      this.moveNode = new BaseNode();
    }
    // 鼠标移出区域/松开鼠标时，停止移动
    this._viewAreaEl.onmouseleave = stopMove
    this._viewAreaEl.onmouseup = stopMove
  }






  render() {
    this.renderVoucher()
    this.renderContent()
    this.rendToolbars();
    this._viewAreaEl.appendChild(this.element);
    this._rootEl.appendChild(this._viewAreaEl);
    this.element.onclick = (e) => {
      e.stopPropagation();
      this.menuView.open = false
      if (this._topbar?.methodType !== "select") return
      this.selectNode = this
    }
    this.element.oncontextmenu = (e) => {
      e.preventDefault();
      e.stopPropagation();
    }
  }
}
